/* The state and event class methods definition */

#include <graphviz/gvc.h>

#include "itf_state_transition.h"

double DotDefaultDPI = 72;
double dpi = 96;

// STATE
// ------------------------------------------------------------------------
State::State(unsigned int stateid, Agraph_t* graph) : QGraphicsEllipseItem()
{
    char c_id[10];
    
    id = stateid;
    gvc_graph = graph;
    
    sprintf(c_id, "%d", id);
    gvc_node = agnode(gvc_graph, c_id);
}

void State::draw(QGraphicsScene *scene)
{
    QGraphicsTextItem *textItem;
    
    mexPrintf("%f %f %f %f\n", getCoordX()-(getWidth()/2), getCoordY()-(getHeight()/2), getWidth(), getHeight());
    
    setRect(getCoordX()-(getWidth()/2), getCoordY()-(getHeight()/2), getWidth(), getHeight());
    setPen(QPen(QColor(50, 50, 150)));
    
    QBrush br = QBrush(QColor(255, 150, 50));
    br.setStyle(Qt::Dense3Pattern);
    
    setBrush(br);
    
    setFlag(QGraphicsItem::ItemIsSelectable, true);
    //elItem->setFlag(QGraphicsItem::ItemIsMovable, true);
    
    textItem = new QGraphicsTextItem(QString().setNum(id));
    textItem->setPos(getCoordX()-((textItem->boundingRect()).width())/2, getCoordY()-((textItem->boundingRect()).height())/2);
    
    textItem->setFont(QFont("Helvetica [Cronyx]", 12, QFont::Normal));
    
    scene->addItem((QGraphicsEllipseItem*)this);
    scene->addItem(textItem);
    
}

Agnode_t * State::getAgnode()
{
    return gvc_node;
}

double State::getCoordX() {
	return gvc_node->u.coord.x*(dpi/DotDefaultDPI);
}

double State::getCoordY() {
	return (gvc_graph->u.bb.UR.y - gvc_node->u.coord.y)*(dpi/DotDefaultDPI);
}

double State::getWidth() {
	return gvc_node->u.width*dpi;
}

double State::getHeight() {
	return gvc_node->u.height*dpi;
}

void State::mousePressEvent (QGraphicsSceneMouseEvent * event)
{
    mexPrintf("CLICK\n");
    
    //emit displayStateECDF(clock_samples, n_clock_samples);
}


// EVENT methods
// ------------------------------------------------------------------------
Event::Event(State* s0, State* s1, unsigned int eventid, Agraph_t* graph, ntrieNode* node) : QGraphicsPathItem()
{
    id = eventid;
    gvc_graph = graph;
    gvc_edge = agedge(gvc_graph, s0->getAgnode(), s1->getAgnode());
    ntrie_n = node;
}

void Event::draw(QGraphicsScene *scene) {
    
    setFlag(QGraphicsItem::ItemIsSelectable, true);
    
    drawArrow(scene);
}

void Event::drawArrow(QGraphicsScene *scene) {
    
    double last_x, last_y, angle, defangle;
    qreal x,y,w,h;
    
    QPointF point;
    QLineF *line;
    QMatrix matrix;
    QPolygonF polygon;
    QGraphicsTextItem *textItem;
    
    char tmp[100]="";
    
    
	//Calculate the path from the spline (only one spline, as the graph is strict. If it
    //wasn't, we would have to iterate over the first list too)
    //Calculate the path from the spline (only one as the graph is strict)
    if((gvc_edge->u.spl->list!=0) && (gvc_edge->u.spl->list->size%3 == 1))
    {
        //If there is a starting point, draw a line from it to the first curve point
        if(gvc_edge->u.spl->list->sflag)
        {
            shape.moveTo(gvc_edge->u.spl->list->sp.x*(dpi/DotDefaultDPI),
                         (gvc_graph->u.bb.UR.y - gvc_edge->u.spl->list->sp.y)*(dpi/DotDefaultDPI));
            shape.lineTo(gvc_edge->u.spl->list->list[0].x*(dpi/DotDefaultDPI),
                    (gvc_graph->u.bb.UR.y - gvc_edge->u.spl->list->list[0].y)*(dpi/DotDefaultDPI));
            last_x = gvc_edge->u.spl->list->list[0].x*(dpi/DotDefaultDPI);
            last_y = (gvc_graph->u.bb.UR.y - gvc_edge->u.spl->list->list[0].y)*(dpi/DotDefaultDPI);
        }
        else {
            shape.moveTo(gvc_edge->u.spl->list->list[0].x*(dpi/DotDefaultDPI),
                    (gvc_graph->u.bb.UR.y - gvc_edge->u.spl->list->list[0].y)*(dpi/DotDefaultDPI));
            last_x = gvc_edge->u.spl->list->list[0].x*(dpi/DotDefaultDPI);
            last_y = (gvc_graph->u.bb.UR.y - gvc_edge->u.spl->list->list[0].y)*(dpi/DotDefaultDPI);
        }

        //Loop over the curve points
        for(int i=1; i<gvc_edge->u.spl->list->size; i+=3) {
            shape.cubicTo(gvc_edge->u.spl->list->list[i].x*(dpi/DotDefaultDPI), 
                  (gvc_graph->u.bb.UR.y - gvc_edge->u.spl->list->list[i].y)*(dpi/DotDefaultDPI),
                  gvc_edge->u.spl->list->list[i+1].x*(dpi/DotDefaultDPI),
                  (gvc_graph->u.bb.UR.y - gvc_edge->u.spl->list->list[i+1].y)*(dpi/DotDefaultDPI),
                  gvc_edge->u.spl->list->list[i+2].x*(dpi/DotDefaultDPI),
                  (gvc_graph->u.bb.UR.y - gvc_edge->u.spl->list->list[i+2].y)*(dpi/DotDefaultDPI));

            last_x = gvc_edge->u.spl->list->list[i+2].x*(dpi/DotDefaultDPI);
            last_y = (gvc_graph->u.bb.UR.y - gvc_edge->u.spl->list->list[i+2].y)*(dpi/DotDefaultDPI);
        }

        //If there is an ending point, draw a line to it
        if(gvc_edge->u.spl->list->eflag)
            shape.lineTo(gvc_edge->u.spl->list->ep.x*(dpi/DotDefaultDPI),
                         (gvc_graph->u.bb.UR.y - gvc_edge->u.spl->list->ep.y)*(dpi/DotDefaultDPI));
    }

    line = new QLineF(last_x, last_y, gvc_edge->u.spl->list->ep.x*(dpi/DotDefaultDPI), (gvc_graph->u.bb.UR.y - gvc_edge->u.spl->list->ep.y)*(dpi/DotDefaultDPI));
    angle = acos(line->dx() / line->length());
    
    defangle = angle * (180/3.14);
    
    //fprintf(stdout, "%f %f\n", angle, defangle);
    
    if (line->dx() > 0 && line->dy() < 0)
        defangle = 360-defangle;
    
    if (line->dx() <= 0 && line->dy() < 0)
        defangle = (180-defangle)+180;
    
    if (line->dy() >= 0)
        defangle = defangle;
    
    point = shape.pointAtPercent(0.5);
    
    matrix.rotate(defangle-90);
    
    polygon << QPointF(0, -10) << QPointF(5, -15) << QPointF(0, 0) << QPointF(-5, -15) << QPointF(0, -10);
    //polygon << QPointF(0, 0) << QPointF(-10, 0) << QPointF(0, 0) << QPointF(0, 20);
    
    polygon = matrix.map(polygon);
    
    polygon.translate(QPointF(gvc_edge->u.spl->list->ep.x*(dpi/DotDefaultDPI), (gvc_graph->u.bb.UR.y - gvc_edge->u.spl->list->ep.y)*(dpi/DotDefaultDPI)));
    
    shape.addPolygon(polygon);
    
    setPath(shape);
    setPen(QPen(QColor("blue")));
    //setBrush(QBrush(QColor("black")));
    
    
    sprintf(tmp, "%d", id);
    
    
    textItem = new QGraphicsTextItem (QString(tmp));
    
    textItem->boundingRect().getRect(&x, &y, &w, &h);
    
    textItem->setPos(point.x() - w/2 + 5, point.y() - h/2);
    
    scene->addItem(this);
    scene->addItem(textItem);
}

void Event::mousePressEvent(QGraphicsSceneMouseEvent * event)
{
    mexPrintf("CLICK Class Event\n");
    
    emit displayECDF(ntrie_n->clks, ntrie_n->clks_size, id, 1);
}
